#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <easyx.h>
#include <graphics.h>


//表示4*4矩阵方格
int array[4][4] = { 0 };

//空位数组
int NullCount = 0;//记录数量
int NullPos[2][16] = {0};//记录行列数据

//窗口句柄
HWND window = nullptr;
 
//图片数组
const char*picture[]={"image/0.png","image/2.png","image/4.png","image/8.png",
"image/16.png","image/32.png","image/64.png","image/128.png",
"image/256.png","image/512.png","image/1024.png","image/2048.png"};

//打印矩阵方格数据
void PrintArray()
{
//	遍历数组（i表示行，j表示列）
	for(int i = 0;i < 4;i++)
	{
		for (int j = 0;j < 4;j++)
		{
			printf("%d\t",array[i][j]);
		}
		printf("\n");
	}
}

//获取空位
int GetNullPos()
{
	NullCount = 0;
	
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			if(array[i][j]==0)
			{
				//记录行和列
				NullPos[0][NullCount] = i;
				NullPos[1][NullCount] = j;
				
				//更新空位个数
				NullCount++;
				}	
		}
	}
	return NullCount;
}

//随机位置随机数生成
void CreatRandData(int count)
{
	//设置时间种子
	srand(time(0));
	
	//判断是否还存在空位，同时更新空位数据
	for(int c = 0;c < count;c++)
	{
	
		if(GetNullPos()==0)
		return;
		//随机一个数表示在NullPos的位置
		int pos = rand()%NullCount;
	
		//生成2/4
		int i = NullPos[0][pos];
		int j = NullPos[1][pos];
		array[i][j] = (rand()%2+1)*2;
	}	
}

//向左移动合并
void left()
 {
	//遍历行
	for (int i = 0;i < 4;i++)
	{
		//遍历列
		for(int j = 0;j < 4;j++)
		{
			//从i行最开始找空位（用0表示）
			if(array[i][j]==0)  //如果i行，j列是0
			{
				//从后面找一个数（不为0）补到这个空位
				for (int t = j + 1;t < 4;t++)
				{
					//判断后面找到的位置是不是空位，不是则搬到空位
					if(array[i][t]!= 0)
					{
						//交换位置
						array[i][j] = array[i][t];
						array[i][t] = 0;
						
						break;
						
						
					}
				}
			}
			//如果不为0，要合并
			if(array[i][j]!=0)
			{
				//从后面找一个和当前数据相同的数据
				for(int t = j + 1;t < 4;t++)
				{
					//遇到相同的合并，遇到0跳过，遇到既不相同也不为0的，直接结束
					if (array[i][t]==array[i][j])
					{
						
						array[i][j]*=2;
						array[i][t] =0;
						
						break;
					}
					else if(array[i][t]==0)
						continue;
					else
						break;
				}
				
			}
			
		}
	}
	CreatRandData(1);
}

//向右移动合并
void right()
{
	//遍历行
	for (int i = 0;i < 4;i++)
	{
		//遍历列
		for(int j = 3;j >=0;j--)
		{
			//找空位
			if(array[i][j]==0) 
			{
				//从前面找一个数（不为0）
				for (int t = j - 1;t >= 0;t--)
				{
					//找到一个不为0的位置
					if(array[i][t]!= 0)
					{
						//交换位置
						array[i][j] = array[i][t];
						array[i][t] = 0;
						
						break;
						
						
					}
				}
			}
			//如果不为0
			if(array[i][j]!=0)
			{
				for(int t = j-1;t >= 0;t--)
				{
					//遇到相同的合并，遇到0跳过，遇到既不相同也不为0的，直接结束
					if (array[i][t]==array[i][j])
					{
						
						array[i][j]*=2;
						array[i][t] =0;
						
						break;
					}
					else if(array[i][t]==0)
						continue;
					else
						break;
				}
				
			}
		}
	}
	CreatRandData(1);
}

//向上移动合并
void up()
{
//	遍历列
	for (int j = 0;j < 4;j++)
	{
		//遍历行
		for(int i= 0;i < 4;i++)
		{
			//找空位
			if(array[i][j]==0)  
			{
				//从下面找一个数（不为0）补到这个空位
				for (int t = i + 1;t < 4;t++)
				{
					if(array[t][j]!= 0)
					{
						//交换位置
						array[i][j] = array[t][j];
						array[t][j] = 0;
						
						break;
						
						
					}
				}
			}
			//如果不为0
			if(array[i][j]!=0)
			{
				for(int t = i + 1;t < 4;t++)
				{
					//遇到相同的合并，遇到0跳过，遇到既不相同也不为0的，直接结束
					if (array[t][j]==array[i][j])
					{
						
						array[i][j]*=2;
						array[t][j]=0;
						
						break;
					}
					else if(array[t][j]==0)
						continue;
					else
						break;
				}
				
			}
		}
	}
	CreatRandData(1);
}

//向下移动合并
void down()
{
//	遍历列
	for (int j = 0;j < 4;j++)
	{
		//遍历行
		for(int i= 3;i >=0;i--)
		{
			//找空位
			if(array[i][j]==0)  
			{
				//从下面找一个数（不为0）补到这个空位
				for (int t = i - 1;t >=0;t--)
				{
					if(array[t][j]!= 0)
					{
						//交换位置
						array[i][j] = array[t][j];
						array[t][j] = 0;
						
						break;
						
						
					}
				}
			}
			//如果不为0
			if(array[i][j]!=0)
			{
				for(int t = i-1;t >=0;t--)
				{
					//遇到相同的合并，遇到0跳过，遇到既不相同也不为0的，直接结束
					if (array[t][j]==array[i][j])
					{
						
						array[i][j]*=2;
						array[t][j]=0;
						
						break;
					}
					else if(array[t][j]==0)
						continue;
					else
						break;
				}
				
			}	
		}
	}
	CreatRandData(1);
}

//判断是否已满（是否存在空位）
int IsFull()
{
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			if(array[i][j]==0)
			{
			return 1;	
			}
		}
	}
	return 0;
}

//是否能合并
int CanMerge()
{
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			if(j+1 < 4 &&(array[i][j] == array[i][j+1])||
			   i+1 < 4 &&(array[i][j] == array[i+1][j]))
			{
			return 1;	
			}
		}
	}
	return 0;
}


//初始化游戏数据
void InitData()
{
	//初始化格子矩阵
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			array[i][j] = 0;
		}
	}
	CreatRandData(2);
}

//----------------------------------------界面----------------------------------------
int log(int n)
{
	if(n<=1)
		return 0;
		
	int count = 0;
	while(n>1)
	{
		count++;
		n/=2;
	}
	return count;
}

void InitWindow()
{
	//创建窗口
	window = initgraph(450,500);
	
	//生成游戏标题
	settextcolor(WHITE);
	settextstyle(40,0,_T("黑体"));
	outtextxy(185,5,"2048");
	
}
void updata()
{
	//生成矩阵格子
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			int pos = log(array[i][j]);
			
			//加载图片
			IMAGE img;
			loadimage(&img,picture[pos]);
			
			//显示图片
			putimage(10+(100+10)*j,50+(100+10)*i,&img); 
			
			
		}
	}
}
//游戏结束
int GameOver()
{
	if(IsFull() == 0&&CanMerge() == 0)  //既没有空位也没有能合并的
	{	
		cleardevice();  //清空屏幕
		updata();
		//生成游戏结束标题
		settextcolor(WHITE);
		settextstyle(80,0,_T("黑体"));
		outtextxy(65,210,"游戏结束");
		
		return 1;
	}
	
	return 0;
}

//游戏成功
void Success()
{
	for(int i = 0;i < 4;i++)
	{
		for(int j = 0;j < 4;j++)
		{
			if(array[i][j] == 2048)
			{
				//生成游戏成功标题
				settextcolor(WHITE);
				settextstyle(80,0,_T("黑体"));
				outtextxy(65,210,"游戏成功");
		
			}
				
		}
	}
}
int main()
{
	//初始化数据
	InitData();
	
	//初始化窗口
	InitWindow();
	

	
	//游戏主逻辑
	while(IsWindow(window)&&GameOver() == 0)
	{	
		updata();
		ExMessage msg;
		
		if(false==peekmessage(&msg))
			continue;
		if(msg.message == WM_KEYDOWN)
		{
			switch(msg.vkcode)
			{
			case VK_UP:
				up();
				break;
			case VK_DOWN:
				down();
				break;
			case VK_LEFT:
				left();
				break;
			case VK_RIGHT:
				right();
				break;
			default:
				continue;
			}
			Success();
		}
			
	}

	system("pause");
	closegraph();
	return 0;
}